#include <iostream>

using std::cout;
using std::endl;
using std::string;

class DecodeStrategy
{
public :
    virtual ~DecodeStrategy();
    virtual char decode(int i) = 0;
    virtual bool should_flip(int i) = 0;
    virtual DecodeStrategy* next_strategy() = 0;
};

class UpperCaseDecodeStrategy : public DecodeStrategy
{
public :
    virtual char decode(int i);
    virtual bool should_flip(int i);
    virtual DecodeStrategy* next_strategy();
};

class LowerCaseDecodeStrategy : public DecodeStrategy
{
public :
    virtual char decode(int i);
    virtual bool should_flip(int i);
    virtual DecodeStrategy* next_strategy();
};

class PunctuationDecodeStrategy : public DecodeStrategy
{
public :
    virtual char decode(int i);
    virtual bool should_flip(int i);
    virtual DecodeStrategy *next_strategy();
};

DecodeStrategy::~DecodeStrategy()
{
}

char
LowerCaseDecodeStrategy::decode(int i)
{
    return 'a' + ((i % 27) - 1);
}

bool
LowerCaseDecodeStrategy::should_flip(int i)
{
    return (i % 27) == 0;
}

DecodeStrategy*
LowerCaseDecodeStrategy::next_strategy()
{
    return new PunctuationDecodeStrategy();
}

char
UpperCaseDecodeStrategy::decode(int i)
{
    return 'A' + ((i % 27) - 1);
}

bool
UpperCaseDecodeStrategy::should_flip(int i)
{
    return (i % 27) == 0;
}

DecodeStrategy*
UpperCaseDecodeStrategy::next_strategy()
{
    return new LowerCaseDecodeStrategy();
}

char
PunctuationDecodeStrategy::decode(int i)
{
    int m = i % 9;

    switch(m) {
    case 1 : return '!';
    case 2 : return '?';
    case 3 : return ',';
    case 4 : return '.';
    case 5 : return ' ';
    case 6 : return ';';
    case 7 : return '"';
    case 8 : return ',';
    }

    return '\0';
}

bool
PunctuationDecodeStrategy::should_flip(int i)
{
    return (i % 9) == 0;
}

DecodeStrategy*
PunctuationDecodeStrategy::next_strategy()
{
    return new UpperCaseDecodeStrategy();
}

class Decoder
{
public :
    Decoder();
    std::string get_message();
    void feed(int i);
private :
    std::string current;
    DecodeStrategy* ds;

    void next_strategy();
};

Decoder::Decoder()
{
    current = "";
    ds = new UpperCaseDecodeStrategy();
}

std::string
Decoder::get_message()
{
    return current;
}

void
Decoder::feed(int i)
{
    if (ds->should_flip(i)) {
        next_strategy();
    } else {
        current += ds->decode(i);
    }
}

void
Decoder::next_strategy()
{
    DecodeStrategy* n = ds->next_strategy();

    delete ds;

    ds = n;
}

int
main(int argc, char **argv)
{
    Decoder d;

    d.feed(18);
    d.feed(12312);
    d.feed(171);
    d.feed(763);
    d.feed(98423);
    d.feed(1208);
    d.feed(216);
    d.feed(11);
    d.feed(500);
    d.feed(18);
    d.feed(241);
    d.feed(0);
    d.feed(32);
    d.feed(20620);
    d.feed(27);
    d.feed(10);

    cout << d.get_message() << endl;
}
